require 'common_stuff'

class UserController < ApplicationController
  include CommonStuff
  skip_before_action :check_login, only: [:login, :logout, :signup ,:create ,:homepage,:checkUsernameRepetition]
  # before_filter :check_login_homepage, only: :homepage

  def index
    puts "=====",__method__,"====="
  end




  def change_profile
    puts "=====",__method__,"====="
    user_name=session[:user_name]
    password=params[:password]
    ptracker_token=params[:ptracker_token]
    user=User.find_by(user_name:user_name)
    salt=BCrypt::Engine.generate_salt
    if user.update(password_salt:salt,
                   password_hash:BCrypt::Engine.hash_secret(password,salt))
      redirect_to user_index_path, :notice => "Profile updated!"
    else  
      flash.now.alert="can't add pivotal tracker token, please try again"
      render :setting
    end
  end




  def login
    user = User.authenticate(params[:user_name], params[:password])

    if user
      userX=User.find_by(user_name:user.user_name)
      session[:ptracker_token]=userX.ptracker_token
      session[:user_name] = user.user_name
      session[:ptracker_user_name] = user.ptracker_user_name
      redirect_to user_index_path, :notice => "Welcome , "+user.user_name
    else
      redirect_to root_url, :notice => "Invalid username or password!"
    end
  end

  def logout
    puts "=====",__method__,"====="
    reset_session
    redirect_to root_url, :notice => "Logged out!"
  end

  def change
    puts "=====",__method__,"====="
  end

  def people
    puts "=====",__method__,"====="
  end


  def checkUsernameRepetition
    puts "=====",__method__,"====="
    user_name=params[:user_name]
    user=User.find_by(user_name:user_name)
    if user!=nil
      # respond_to do |format|
      render :text=> user_name+" exists"
      # end
    else
      # respond_to do |format|
      render :text=> "OK"
      # end
    end
  end


  def signup
    puts "=====",__method__,"====="
  end

  def create
    puts "=====",__method__,"====="
    user_name=params[:user_name]
    password=params[:password]

    @new_user=User.new
    @new_user.user_name=user_name
    @new_user.password_salt = BCrypt::Engine.generate_salt
    @new_user.password_hash = BCrypt::Engine.hash_secret(password, @new_user.password_salt)

    if @new_user.save
      session[:user_name] = user_name
      redirect_to user_first_setting_path, :notice => "Signed up!"
    else
      redirect_to user_signup_path, :notice => "Sign up failed!"
    end
  end

  def first_setting
    puts "=====",__method__,"====="
  end

  def setting
    puts "=====",__method__,"====="
    @user_name=session[:user_name]
    @ptracker_token=session[:ptracker_token]
  end


  def show
    puts "=====",__method__,"====="
  end

  def homepage
    puts "=====",__method__,"====="
    @user=User.new
  end


  def get_projects
    puts "=====",__method__,"====="
    ptracker_token =params[:ptracker_token]
    github_token   =params[:github_token]
    user_name=session[:user_name]

    #get pivotal tracker user info
    client = TrackerApi::Client.new(token: ptracker_token)
    ptracker_user_name=client.me.name
    
    message=check_ptracker_token_sanity(ptracker_token,user_name)
    if  message!= "Valid"
      @token_sanity=false
      @token=ptracker_token
      @message=message
      return
    end

    @token_sanity=true
    

    


    user = User.find_by(user_name: user_name)
    if user.update(ptracker_token: ptracker_token , github_token:github_token,ptracker_user_name:ptracker_user_name)
      session[:ptracker_token]=ptracker_token
      session[:ptracker_user_name]=client.me.name
      session[:github_token]=github_token
      # redirect_to user_index_path , :notice => "Pivotal Tracker token added!"
    else  
      flash.now.alert="can't add pivotal tracker token, please try again"
      render :first_setting
    end
    @projects=get_projects_info_by_token(ptracker_token,user_name)

  end

  def process_selected_projects
    ptracker_token=session[:ptracker_token]
    github_token = session[:github_token]
    puts "github_token:",github_token
    user_name=session[:user_name]
    client = TrackerApi::Client.new(token: ptracker_token) 

    msg=params[:msg]
    project_ids=JSON.parse(msg)

    arr_projects=Array.new
    project_ids.each_with_index do |p,index|
      print "project"+index.to_s+":"+p+"\n"
  
      p=client.project(p.to_i)
      arr_projects.push(p)
      print " Project:",p.name,"\n"
      mX=Member.find_by(project_id:p.id.to_s)

      project=Project.new
      project.project_id=p.id
      project.project_name=p.name
      project.user_name=user_name
      project.save!
    
      if mX!=nil
        print "  !!!",p.name," 's member info has already been loaded to db\n"
      else
        p.memberships.each do |ms|
          member=Member.new
          member.project_id=p.id
          member.member_name=ms.person.name
          member.role=ms.role
          member.save!
          print "   membership:",ms.person.name," ",ms.role,"\n"
        end
      end  

    end

    pentry_init(ptracker_token,arr_projects)
    state_trans_and_github_init(ptracker_token,github_token)
    done_story_init(ptracker_token)



    # render plain: "123"
  end

  # def add_ptracker_token
  #   puts "=====",__method__,"====="
  #   ptracker_token=params[:ptracker_token]
  #   github_token  =params[:github_token]
  #   user_name=session[:user_name]

  #   message=check_ptracker_token_sanity(ptracker_token,user_name)
  #   if  message!= "Valid"
  #     @token_sanity=false
  #     @token=ptracker_token
  #     @message=message
  #     return
  #   end

  #   @token_sanity=true
    
  #   user = User.find_by(user_name: user_name)
  #   if user.update(ptracker_token: ptracker_token , github_token:github_token)
  #     session[:ptracker_token]=ptracker_token
  #     @client=get_ptracker_info_by_token(ptracker_token,user_name)
  #     # redirect_to user_index_path , :notice => "Pivotal Tracker token added!"
  #   else  
  #     flash.now.alert="can't add pivotal tracker token, please try again"
  #     render :first_setting
  #   end
  #   @projects=Project.where("user_name=?",user_name)
  #   @members=Member.find_by_sql("SELECT DISTINCT member_name FROM members WHERE project_id in(select distinct project_id from projects where user_name ='" + user_name +"')")

  #   pentry_init(ptracker_token)
  #   state_trans_and_github_init(ptracker_token,github_token)
  #   done_story_init(ptracker_token)

  # end



  def user_params
    params.require(:user).permit(:user_name, :password)
  end

  def check_ptracker_token_sanity(token,user_name)
      puts "=====",__method__,"====="

      userX=User.find_by(ptracker_token:token)
      if(userX!=nil)
        return "This token has been taken by another user"
      end

      userX=User.find_by(user_name:user_name)
      puts "1:",userX.ptracker_token
      if userX.ptracker_token!=nil
        return "You can not set up Pivotal Tracker token twice"
      end

      trackerurl = "https://www.pivotaltracker.com/services/v5/accounts/100";
      puts "trackerurl:",trackerurl
      c = Curl::Easy.new(trackerurl) do |curl| 
          curl.headers["X-TrackerToken"] = token
          curl.verbose = true
      end
      c.perform
      # puts c.body_str
      
      body = JSON.parse(c.body_str)
      print "body:\n"
      print body
      if body["code"]=="invalid_authentication"
        return "This token can not be identified by Pivotal Tracker"
      end
      return "Valid"
  end


  def get_ptracker_info_by_token(token,user_name)
    puts "=====",__method__,"====="
    client = TrackerApi::Client.new(token: token) 
    # save user's ptracker name
    user = User.find_by(user_name: user_name)
    # puts "11:",client.me.name
    user.update(ptracker_user_name: client.me.name)
    session[:ptracker_user_name]=client.me.name
    projects=client.projects
    projects.each do |p|
      print " Project:",p.name,"\n"
      mX=Member.find_by(project_id:p.id.to_s)

      project=Project.new
      project.project_id=p.id
      project.project_name=p.name
      project.user_name=user_name
      project.save!
    
      if mX!=nil
        print "  !!!",p.name," 's member info has already been loaded to db\n"
      else
        p.memberships.each do |ms|
          member=Member.new
          member.project_id=p.id
          member.member_name=ms.person.name
          member.role=ms.role
          member.save!
          print "   membership:",ms.person.name," ",ms.role,"\n"
        end
      end  
    end
  end

  def get_projects_info_by_token(token,user_name)
    puts "=====",__method__,"====="
    client = TrackerApi::Client.new(token: token) 
    # save user's ptracker name
    user = User.find_by(user_name: user_name)
    # puts "11:",client.me.name
    user.update(ptracker_user_name: client.me.name)
    session[:ptracker_user_name]=client.me.name
    projects=client.projects
    return projects
  end

  def delete_ptracker_info
    puts "=====",__method__,"====="
  end

  def check_login_homepage
    puts "=====",__method__,"====="
    if(!session[:user_name])
      # flash.now.notice="Please login first"
      # redirect_to user_homepage_path , :notice => "Please login first."
    end
  end



  #helper
  def pentry_init(ptracker_token,projects)
    puts "=====",__method__,"====="


    # token =session[:ptracker_token].to_s
    # client = TrackerApi::Client.new(token: token) 
    # projects=client.projects
    projects.each do |project|
      print "Project: ",project.name,"\n"
      stories=project.stories()
      # stories=project.stories(updated_after:date_after,updated_before:date_before)
      stories.each do |story|
        # save entries in our database
        print "    Story: ",story.name,"\n"
        status=GetStatusFromStoryLabel(story)
        puts "       current_state:",story.current_state
        # puts Date.today.to_formatted_s(:db).to_s
        # puts "story.id:",story.id
        # puts PEntry.exists?(:ptracker => story.id)

        
        p_entry=PEntry.new()

        p_entry.story_id=story.id
        p_entry.token=ptracker_token
        p_entry.project_id=story.project_id
        p_entry.project_name=project.name
        p_entry.story_name=story.name
        p_entry.story_type=story.story_type
        p_entry.story_description=story.description
        p_entry.current_state=story.current_state
        p_entry.date=GetFormattedDateFieldFromPT(story.updated_at)
        p_entry.status=status
        p_entry.pt_created_at=story.created_at
        p_entry.pt_updated_at=story.updated_at 
        p_entry.deadline=story.deadline
        p_entry.url=story.url

        p_entry.save!
  
      end
    end

  end




  def state_trans_and_github_init(ptracker_token,github_token)
    puts "=====",__method__,"====="


    date=Date.today.to_formatted_s(:db).to_s
    p_entry= PEntry.where("token=?" ,ptracker_token)


    p_entry.each do |pe|
      trackerurl = "https://www.pivotaltracker.com/services/v5/projects/"+pe.project_id.to_s+"/stories/"+pe.story_id.to_s+"/activity"
     
      story_updateX=StoryUpdate.find_by(story_id:pe.story_id.to_s)
      if story_updateX!=nil
         trackerurl+= "?occurred_after="+story_updateX.ac_update_before.to_s
      end
      puts "trackerurl:",trackerurl
      c = Curl::Easy.new(trackerurl) do |curl| 
          curl.headers["X-TrackerToken"] = session[:ptracker_token].to_s
          curl.verbose = true
      end
      c.perform
      # puts c.body_str
      
      activities = JSON.parse(c.body_str)
      if story_updateX==nil or story_updateX.cm_update_before==nil or story_updateX.ac_update_before==nil
         ac_update_before="0"
         cm_update_before="0"
      else
         ac_update_before=story_updateX.ac_update_before
         cm_update_before=story_updateX.cm_update_before
      end

      # puts "acti:",activities

      puts "activities number:",activities.length
      activities.each do |activity|
        # puts activity["kind"]
        if ac_update_before<activity["occurred_at"]
          ac_update_before=activity["occurred_at"]
        end

    # ========state_trans stuff
        if activity["changes"] == nil
          next
        else
          activity["changes"].each do |change|
              story_state_trans = StateTrans.new()
              story_state_trans.story_id=pe.story_id.to_s

              if change["original_values"] == nil
                next
              else
                if change["original_values"]["current_state"]==nil
                  next
                else
                  story_state_trans.current_state=change["original_values"]["current_state"]
                end
              end

              if change["new_values"] == nil
                next
              else
                story_state_trans.new_state=change["new_values"]["current_state"]
              end

              if change["new_values"]["updated_at"]==nil
                next
              else
                story_state_trans.commit_time=change["new_values"]["updated_at"]
              end

              story_state_trans.save!
          end
        end

    # ========github stuff  

        if activity["kind"]=="comment_create_activity"
          puts activity["kind"]
          if activity["changes"]==nil
            next
          else
            activity["changes"].each do |change|
              puts "new values",change["new_values"]
              if change["new_values"]["text"]==nil
                next
              else
                puts "comment_url:",change["new_values"]["text"]
                comment_url = change["new_values"]["text"].to_s

                x_url = URI.extract(comment_url, /http(s)?/)
                puts "x_url:",x_url

                array=x_url.to_s.split('/')
                owner=array[3]
                repos=array[4]
                shaPlus=array[6]
                if(shaPlus==nil)
                  puts "shaPlus is nil"
                  next
                end
                sha=shaPlus[0..-3]
                puts owner
                puts repos
                puts sha     
                github_uri = "https://api.github.com/repos/"+owner+"/"+repos+"/commits/"+sha+"?access_token="+github_token
                if story_updateX==nil or story_updateX.cm_update_before==nil
                else
                  github_uri+= "&since="+story_updateX.cm_update_before
                  # params = { :since =>story_updateX.cm_update_before} 
                end

                puts "github_url:",github_uri
                c = Curl::Easy.new(github_uri) do |curl| 
                    curl.headers["User-Agent"]=owner
                    curl.verbose = true


                end
                c.perform


                # uri.query = URI.encode_www_form(params)
                
                # res = Net::HTTP.get_response(URI(uri))
                # res_status=c.header_str.scan(/HTTP\/\d\.\d\s(\d+\s.+)\r\n/).map{ |match|  match[0] }
                res_status=c.header_str.split(' ')[1]
                puts "header.status:",res_status
                puts "body:",c.body_str

                if res_status!="200"
                  puts "Response status not ok , can't get data from github by: ",x_url
                  next
                else
                  hash =JSON.parse c.body_str
                  commit_timeX=hash["commit"]["committer"]["date"]
                  puts "!!!!date:",commit_timeX

                  if cm_update_before<commit_timeX
                    cm_update_before=commit_timeX
                  end
                  puts "stats:",hash["stats"]
                  

                  stats=GithubStat.new
                
                  stats.story_id=pe.story_id
                  stats.committer_github=hash["commit"]["committer"]["name"]
                  stats.commit_time=hash["commit"]["committer"]["date"]
                  stats.total=hash["stats"]["total"]
                  stats.addition=hash["stats"]["additions"]
                  stats.deletion=hash["stats"]["deletions"]
                  stats.message=hash["commit"]["message"]
                  stats.committer_ptracker , stats.status =parse_message(stats.message)
                  stats.file=hash["files"].to_s

                  stats.save!
                end
                # api_uri="https://api.github.com/repos/"+owner+"/"+repos+"/commits/"+sha
                # res= Net::HTTP.get(URI(api_uri))
                
                # puts "res.code:",res.code
                # if(res.code!='200')
                #   puts "Response status not ok , can't get data from github by: ",url
                #   next
                # else
                #   hash =JSON.parse res.body
                #   # puts JSON.pretty_generate(hash)
                #   print "hash.length:",hash.length,"\n"
                #   # print "hash:",hash,"\n"

  

                #   if hash["message"]=="Not Found"
                #     print "Can't find url:",uri,"\n"
                #     next
                #   end

                #   commit_timeX=hash["commit"]["committer"]["date"]
                #   puts "!!!!date:",commit_timeX

                #   if cm_update_before<commit_timeX
                #     cm_update_before=commit_timeX
                #   end
                #   puts "stats:",hash["stats"]
                  

                #   stats=GithubStat.new
                
                #   stats.story_id=pe.story_id
                #   stats.committer_github=hash["commit"]["committer"]["name"]
                #   stats.commit_time=hash["commit"]["committer"]["date"]
                #   stats.total=hash["stats"]["total"]
                #   stats.addition=hash["stats"]["additions"]
                #   stats.deletion=hash["stats"]["deletions"]
                #   stats.message=hash["commit"]["message"]
                #   stats.committer_ptracker , stats.status =parse_message(stats.message)
                #   stats.file=hash["files"].to_s

                #   stats.save!
                # end
              end
            end
          end
        end
      end


      puts "ac_update_before,",ac_update_before
      if story_updateX==nil
          story_update=StoryUpdate.new
          story_update.story_id=pe.story_id
          story_update.ac_update_before=ac_update_before
          story_update.cm_update_before=cm_update_before
          story_update.save!
      else
          story_updateX.update(ac_update_before:ac_update_before)
          story_updateX.update(cm_update_before:cm_update_before)
      end

    end

    # render plain: "Signup failed."

  end

  def testgithub
    owner="flybrother"
    repos="rtest"
    sha="a990c4fc4850a14d5e6f1d01c62fe9733e19726c"
    # uri = "https://api.github.com/repos/"+owner+"/"+repos+"/commits/"+sha
    uri ="https://api.github.com/repos/PWCLabs/ETBaseballCardGenerator/commits/3f993f756530807a81cc7fa44e77b9fa26bde373?access_token=ea13e2d0dbd091e8264cf1bea76b5967157aa4ee"
# uri="https://api.github.com/user"
      c = Curl::Easy.new(uri) do |curl| 
          curl.headers["User-Agent"] = "PWCLabs"
          # curl.headers["Authorization"] = 'token ea13e2d0dbd091e8264cf1bea76b5967157aa4ee'
          curl.verbose = true
      end

      # c.http_auth_types = :basic
      # c.username = 'be3851f9a144a69ca67696a2b5c9e951de39a416'
      # c.password = 'x-oauth-basic'
      c.perform
      res_status=c.header_str.scan(/HTTP\/\d\.\d\s(\d+\s.+)\r\n/).map{ |match|  match[0] }
      puts "header.status:",c.header_str.split(' ')[1]
      puts "body:",c.body_str
      
      # activities = JSON.parse(c.body_str)
      render plain: "123"
  end

  def done_story_init(ptracker_token)
    puts "=====",__method__,"====="
    # token = session[:ptracker_token].to_s
    date  = Date.today.to_formatted_s(:db).to_s
    entry = PEntry.where("token = ?",ptracker_token)

    entry.each do |e|
      start_time = StateTrans.find_by_sql("Select commit_time from state_trans where story_id = '"+e.story_id.to_s+"'and current_state='unstarted' and new_state='started' limit 1")
      end_time = StateTrans.find_by_sql("Select commit_time from state_trans where story_id = '"+e.story_id.to_s+"'and current_state='started' and new_state='finished' limit 1")
      if(start_time.first==nil and end_time.first==nil)
        puts "in schedule"
      elsif(start_time.first!=nil and end_time.first==nil)
        puts "in process"
      elsif(start_time.first==nil and end_time.first!=nil)
        puts "something wrong"
      else
        puts "start_time",start_time.first.commit_time
        puts "end_time",end_time.first.commit_time
        connection = ActiveRecord::Base.connection
        interval=connection.execute("SELECT  '"+end_time.first.commit_time.to_s+"'::timestamp - '"+start_time.first.commit_time.to_s+"'::timestamp as intervaltime")
        puts "interval:",interval.first["intervaltime"]
        save_in_done(interval.first["intervaltime"],e,date)
      end
    end

  end



  def GetStatusFromStoryLabel(story)
      labels=story.labels
      puts "labels:",labels.length
      status=-1
      labels.each do |label|
        r=labeltoStatus(label.name.to_s)
        puts "r:",r
        if(r!= "NOTHLABEL")
          status=r
          puts "status",status 
          return status
        end
      end
      puts "status",status 
      return status
  end

  def labeltoStatus(label)
    puts "====labeltoStatus started"
    arr=label.split('#')
    puts "labeltostatus:",arr
    if(arr[0] != 'h')
      return "NOTHLABEL"
    else
      puts arr[1]
      # arr2=arr[1].split('%')
      # puts arr2
      # return arr2[0]
      return arr[1]
    end
  end

  def GetFormattedDateFieldFromPT(date)
     ar=date.to_s.split(" ")
     puts "GetFormattedDateFieldFromPT:",ar[0].to_s
     return ar[0].to_s
  end

end